home *** CD-ROM | disk | FTP | other *** search
- /*
- * Demo of using clip2gif with the CFM PPC
- *
- * PLASE READ!
- *
- * This CGI program returns a GIF showing the trajectory of a planar parallel robot.
- * If should be saved as robot.acgi. It can be called with the following URLs:
- *
- * http://your.hostname/robot.acgi?k=h&w=5&h=7&n=10
- * -> html page wrapping an image of a robot with a motion of width 20 * w,
- * height 10 * h, and 2 * n intermediate positions
- * (each argument is coded in 1 char :-( )
- *
- * http://your.hostname/robot.acgi?k=g&w=20&h=30&n=10
- * -> corresponding gif image
- *
- * To compile it, create a new PPC project with CW7 (other versions and compilers
- * might also work, but haven't been tested), include example-cgi.c, LoadClip2Gif.c,
- * InterfaceLib, MWCRuntime.Lib, MathLib and AppleScriptLib, and build it as "robot.acgi".
- * It should have at least canBackground and isHightLevelEventAware bits set.
- * Copy it anywhere in the HTTP server document tree. clip2gif should be on the same
- * volume, or in the same folder if there are former versions on the same volume.
- *
- * To quit robot.acgi, send it a quit AppleEvent ('tell app "robot.acgi" to quit'
- * in AppleScript), or type command-q.
- *
- *** Warning: The purpose of this CGI is *not* to show The Best Way to implement a CGI,
- *** but how simple it is to use clip2gif.
- *
- * Copyright 1995, Yves Piguet. All rights reserved.
- *
- * Can be distributed only as part of the whole clip2gif package.
- *
- * If you use this source code, acknowledgment on your web pages would be appreciated.
- *
- * Thanks!
- */
-
- #include <fp.h> // math functions
- #include <AppleEvents.h>
-
- #include "LoadClip2Gif.h"
-
- int done;
-
- static StringPtr http_html_header = "\pHTTP/1.0 200 OK\r\n\Content-type: text/html\r\n\r\n";
- static StringPtr http_gif_header = "\pHTTP/1.0 200 OK\r\nContent-type: image/gif\r\n\r\n";
- static StringPtr http_error = "\pHTTP/1.0 400 ERROR\r\n\r\n";
-
- // HTML doc. Not that nice to have it here in pascal strings, but you'd been warned.
- // The inline image URL can become robot.acgi?k=h&w=2&h=3&k=g or even
- // robot.acgi?&k=g , but it still works.
-
- static StringPtr html_t1 = "\p<html><header><title>Robot</title></header>\r\n<body><h1>Robot</h1>"
- "Planar parallel robot with horizontal tool base.<p>"
- "<img src=robot.acgi?";
- static StringPtr html_t2 = "\p&k=g><p>\r\n"
- "<hr><h2>New Move</h2>"
- "<form action=robot.acgi method=get>\r\n"
- "<input type=hidden name=k value=h>\r\n"
- "Width: <select name=w>";
- static StringPtr html_t3 = "\p<option value=1>20</option><option value=2>40</option>"
- "<option value=3>60</option><option value=4>80</option>\r\n"
- "<option value=5 selected>100</option><option value=6>120</option>"
- "<option value=7>140</option><option value=8>160</option>"
- "</select><p>\r\n";
- static StringPtr html_t4 = "\pHeight: <select name=h>"
- "<option value=0>0</option><option value=1>10</option>"
- "<option value=2>20</option><option value=3>30</option>\r\n"
- "<option value=4 selected>40</option><option value=5>50</option>"
- "<option value=6>60</option><option value=7>70</option>";
- static StringPtr html_t5 = "\p<option value=8>80</option>"
- "</select><p>\r\n"
- "Intermediate positions: <select name=n>\r\n"
- "<option value=0>0</option><option value=1>2</option>"
- "<option value=2>4</option><option value=4 selected>8</option>"
- "<option value=6>12</option><option value=9>18</option>";
- static StringPtr html_t6 = "\p</select><p>\r\n"
- "<input type=submit value=Submit></form><p>\r\n"
- "<hr><address>CGI written by "
- "<a href=mailto:piguet@ia.epfl.ch>Yves Piguet</a></address>"
- "</body></html>\r\n";
-
- // some geometric constants
-
- #define iw 240
- #define ih 200
-
- #define top 5
- #define ground 195
- #define center 120
- #define shoulder 20
- #define arm 105
- #define forearm 110
- #define paralw 10
-
- static void InitToolbox()
- {
- InitGraf((Ptr)&qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(0L);
- InitCursor();
- }
-
- static pascal OSErr MyHandleQuit(AppleEvent *evt, AppleEvent *reply, long refCon)
- {
- #pragma unused(evt, reply, refCon)
-
- done = 1;
- return noErr;
- }
-
- static void DrawRobot(short a, short b)
- // draws the robot arms to point (a, b) over the ground
- {
- double x, y, tmp, x1, y1;
- short a1, b1;
-
- a1 = a - shoulder;
- b1 = ground - top - b;
-
- tmp = a1 * a1 + b1 * b1;
- x1 = (tmp + arm * arm - forearm * forearm) / (2 * tmp);
- y1 = sqrt(arm * arm / tmp - x1 * x1);
-
- x = a1 * x1 - b1 * y1;
- y = b1 * x1 + a1 * y1;
-
- MoveTo(center - shoulder, top);
- Line((short)x, (short)y);
- LineTo(center + a, ground - b);
- Line(paralw, 0);
-
- MoveTo(center - shoulder + (short)x, top + (short)y);
- Line(paralw, 0);
-
- MoveTo(center - shoulder + paralw, top);
- Line((short)x, (short)y);
- LineTo(center + a + paralw, ground - b);
-
- a1 = a + shoulder;
-
- tmp = a1 * a1 + b1 * b1;
- x1 = (tmp + arm * arm - forearm * forearm) / (2 * tmp);
- y1 = sqrt(arm * arm / tmp - x1 * x1);
-
- x = a1 * x1 + b1 * y1;
- y = b1 * x1 - a1 * y1;
-
- MoveTo(center + shoulder + paralw, top);
- Line((short)x, (short)y);
- LineTo(center + a + paralw, ground - b);
- }
-
- static pascal OSErr MyHandleSDOC(AppleEvent *evt, AppleEvent *reply, long refCon)
- {
- #pragma unused(refCon)
-
- Offscreen os;
- short width = 100, height = 40, n = 10, i;
- unsigned char kind = 'h';
-
- DescType typeCode;
- Size actualSize;
- Str255 arg;
- AEDesc replyStr;
- Handle gifHandle;
- OSErr err;
-
- err = AEGetParamPtr(evt, 'kfor', typeChar, &typeCode, (Ptr)(arg + 1), 250, &actualSize);
- if (err != noErr)
- goto oops;
- arg[0] = actualSize;
-
- for (i = 0; i < arg[0] - 2; i++)
- if (arg[i + 2] == '=')
- switch (arg[i + 1])
- {
- case 'k':
- case 'K':
- kind = arg[i + 3] | 32; // lowercase
- if (kind != 'g')
- kind = 'h';
- arg[i + 2] = 'g'; // ready for the inline image URL
- break;
- case 'w':
- case 'W':
- if (arg[i + 3] >= '0' && arg[i + 3] <= '9')
- width = 20 * (arg[i + 3] - '0');
- else
- width = 100;
- break;
- case 'h':
- case 'H':
- if (arg[i + 3] >= '0' && arg[i + 3] <= '9')
- height = 10 * (arg[i + 3] - '0');
- else
- height = 40;
- break;
- case 'n':
- case 'N':
- if (arg[i + 3] >= '0' && arg[i + 3] <= '9')
- n = 2 * (arg[i + 3] - '0');
- else
- n = 8;
- break;
- }
-
- if (kind == 'h') // HTML
- {
- replyStr.descriptorType = typeChar;
- err = PtrToHand((Ptr)(http_html_header + 1), &replyStr.dataHandle, http_html_header[0]);
- err = PtrAndHand((Ptr)(html_t1 + 1), replyStr.dataHandle, html_t1[0]);
- err = PtrAndHand((Ptr)(arg + 1), replyStr.dataHandle, arg[0]); // part of gif URL
- err = PtrAndHand((Ptr)(html_t2 + 1), replyStr.dataHandle, html_t2[0]);
- err = PtrAndHand((Ptr)(html_t3 + 1), replyStr.dataHandle, html_t3[0]);
- err = PtrAndHand((Ptr)(html_t4 + 1), replyStr.dataHandle, html_t4[0]);
- err = PtrAndHand((Ptr)(html_t5 + 1), replyStr.dataHandle, html_t5[0]);
- err = PtrAndHand((Ptr)(html_t6 + 1), replyStr.dataHandle, html_t6[0]);
- }
- else // GIF
- {
- err = BeginOffscreen(&os, iw, ih, 4, colorPaletteSystem);
- if (err != noErr)
- goto oops;
-
- // now the QuickDraw port is ok; we can draw directly
-
- PenSize(2, 2);
-
- // arms in the intermediate positions
-
- ForeColor(cyanColor);
- for (i = 1; i <= n; i++)
- DrawRobot(-width / 2 + width * i / (n + 1), height * i / (n + 1));
-
- // arms in the extreme positions
-
- ForeColor(blackColor);
- DrawRobot(-width / 2, 0);
- DrawRobot(width / 2, height);
-
- // top (where the robot is fixed)
-
- ForeColor(redColor);
- PenSize(4, 4);
- MoveTo(0, top);
- Line(iw, 0);
- PenSize(1, 1);
-
- // that's it!
-
- //#ifdef noooooh
- {
- // if you want to check the image before launching your http server,
- // enable these lines and send robot.acgi the following AS command:
- // «event WWWΩsdoc» given «class kfor»:"k=g&w=5&h=5&n=5"
-
- FSSpec spec;
- FSMakeFSSpec(0, 0, "\ptest.gif", &spec);
- (void)ConvertPixmapToGIFFile(os.pixmap, &spec, 1, transparencyFirstPixel);
- }
- //#endif
-
- err = ConvertPixmapToGIFHandle(os.pixmap, &gifHandle, 1, transparencyFirstPixel);
-
- if (err == noErr) // concat. the http GIF header and the gif
- {
- replyStr.descriptorType = typeChar;
- err = PtrToHand((Ptr)(http_gif_header + 1), &replyStr.dataHandle, http_gif_header[0]);
- err = HandAndHand(gifHandle, replyStr.dataHandle);
- DisposHandle(gifHandle);
- }
-
- (void)DisposeOffscreen(&os);
- }
-
- oops:
- if (err != noErr)
- {
- replyStr.descriptorType = typeChar;
- err = PtrToHand((Ptr)(http_error + 1), &replyStr.dataHandle, http_error[0]);
- }
-
- (void)AEPutParamDesc(reply, keyDirectObject, &replyStr);
- DisposHandle(replyStr.dataHandle);
-
- return noErr;
- }
-
- void main(void)
- {
- EventRecord myEvent;
- OSErr err;
-
- InitToolbox(); // standard stuff
-
- // uses the CFM to gain access to clip2gif exported functions
-
- err = LoadClip2Gif();
- if (err != noErr)
- {
- SysBeep(1); // Cannot load clip2gif
- return;
- }
-
- // installs AppleEvent handlers for quit and sdoc
-
- (void)AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
- NewAEEventHandlerProc(MyHandleQuit), 0L, 0);
- (void)AEInstallEventHandler('WWWΩ', 'sdoc',
- NewAEEventHandlerProc(MyHandleSDOC), 0L, 0);
-
- // main event loop
-
- for (done = 0; !done;)
- {
- WaitNextEvent(everyEvent, &myEvent, 30L, 0L);
- switch (myEvent.what)
- {
- case keyDown:
- if (myEvent.modifiers & cmdKey
- && (myEvent.message & charCodeMask) == 'q') // command-q -> quit
- done = 1;
- break;
- case kHighLevelEvent:
- (void)AEProcessAppleEvent(&myEvent);
- break;
- }
- }
- }
-